fix: validate duplicate language configurations in CHECKCFG#1376
Draft
joaodinissf wants to merge 4 commits into
Draft
fix: validate duplicate language configurations in CHECKCFG#1376joaodinissf wants to merge 4 commits into
joaodinissf wants to merge 4 commits into
Conversation
133312f to
c89159f
Compare
The CHECKCFG grammar accepts multiple `for <Language> { ... }` blocks in one
configuration. Nothing validated against the same language appearing twice, so
duplicate blocks were silently allowed with no defined semantics for how their
configurations combine.
Add an error-severity validation plus a quick-fix:
- checkConfiguredLanguageUnique on CheckConfiguration reports an error on each
duplicate ConfiguredLanguageValidator sharing a language name. Mirrors the
existing catalog/check/parameter uniqueness validators and reuses the
getDuplicates() helper. Simpler than the catalog case: getLanguage() returns
a String, so no proxy check is needed.
- removeDuplicateLanguageConfiguration quick-fix merges every later block's
parameter and catalog configurations into the first occurrence and deletes
the duplicates.
Tests live in CheckCfgTest; the surrounding checkcfg.core.test validation files
are migrated Xtend -> Java to add them.
This revives the approach from the long-closed dsldevkit#104 (validation + merge
quick-fix), reimplemented against the current Java validator/quick-fix code,
which was renamed and migrated off Xtend since 2018.
Closes dsldevkit#103
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
c89159f to
4bd5ca1
Compare
auto-merge was automatically disabled
June 12, 2026 21:07
Pull request was converted to draft
…ration Extracts the merge logic from the UI quickfix provider's anonymous ISemanticModification into CheckCfgQuickfixes in checkcfg.core, leaving the provider a thin @fix wrapper. The model transformation is now exercisable without an editor or workbench, and CheckCfgQuickfixesTest covers six scenarios (catalog merge, parameter merge, 3+ occurrences, language selectivity, invocation-independence, empty duplicate) against parsed models in checkcfg.core.test. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fdcf350 to
01559a7
Compare
To the reviewer: Thank you — your three findings on the dedup-aware merge were all correct, and this commit is the considered response. The short version: I implemented the deduplication direction your findings pointed at, it made things worse, so I reverted it and kept the original order-preserving concatenation, now with its contract and limitations documented explicitly. Reasoning in full: Findings 1 and 2 (same-catalog merge dropped catalog-level parameters; duplicate-check merge dropped the earlier check's parameters). You were right and these were genuine data loss. Crucially they existed ONLY in the dedup-aware merge I had added, not in the original concatenation: ConfiguredCatalog and ConfiguredCheck both extend ConfigurableSection, so each carries its own parameter configurations, and collapsing same-named catalogs/checks silently dropped them. I have reverted that dedup commit in full. With no deduplication nothing is dropped, so findings 1 and 2 no longer apply to the code under review. Why concatenation rather than a corrected, deeper dedup. The properties generator is last-wins (it puts configurations into a Properties map in order, so a later definition overrides an earlier one). Order-preserving concatenation relocates every entry into one block in its original order, which reproduces the exact generated output of the original duplicate blocks — it is behaviour- preserving. Your findings demonstrated the opposite for dedup: any scheme that removes the resulting language-scoped duplicates ends up dropping scoped parameters the generator would have emitted. A fully faithful dedup would have to replicate the generator's whole inheritance resolution inside the quick-fix, which is disproportionate and a large new bug surface. So the safe choice is to move entries without rewriting them. Finding 3 (language-level parameter rescoping). Agreed, and note it is inherent to collapsing two blocks into one — it is present in any merge, including the original, not something dedup introduced. In the common case it is harmless; in the rare case where the duplicate blocks carry different block-level inherited parameters it genuinely cannot be represented in a single block. We accept this: the quick-fix resolves the duplicate-LANGUAGE error the issue asks for; it does not claim to resolve every downstream inheritance conflict, whose correct resolution depends on user intent the tool cannot infer. Residual unvalidated duplicates (your earlier rounds). The concatenation can leave language-scoped duplicate catalogs/parameters that no validator flags. That validation gap is pre-existing and independent of this change: language- scoped catalog/parameter uniqueness is simply not validated anywhere today, and the originating issue (dsldevkit#103) asks only for duplicate-language validation plus a merge quick-fix, both of which this PR delivers. Adding language-scoped uniqueness validation is worthwhile but is a separate concern, tracked as a follow-up rather than expanding this PR. Until then the residual duplicates are benign at generation (same last-wins outcome). Coverage gap (no @Fix-execution test). Accepted. As you verified, the provider cast is safe by construction — the error is reported on a ConfiguredLanguageValidator source — and the model transformation itself is covered by the core tests. This commit changes only the Javadoc of mergeDuplicateLanguageConfigurations to record the order-preserving contract, the behaviour-preservation rationale, and the documented scope boundary, so the intent is explicit for future readers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
To the reviewer: Your fourth-round finding stands and I have verified it directly: the generator collects inherited parameters by walking parent ConfigurableSections and taking the first occurrence of each name per section (first-wins). So collapsing two duplicate language blocks into one — which any merge must do — moves both blocks' language-level parameters into a single section, and the inner catalogs silently inherit the first value instead of their original per-block value. That is a real generated-output change, and no consolidating merge can avoid it without materializing the generator's full inheritance resolution down into every catalog/check scope, which is disproportionate. This is not specific to my implementation: the rescoping (and the unvalidated language-scoped duplicates from the earlier rounds) is intrinsic to the "merge duplicate language blocks" idea as originally conceived in dsldevkit#104 back in 2018; only the dedup data-loss from fdcf350 was mine, and that was reverted. The merge quick-fix was never safely automatable. So this commit removes the quick-fix entirely and keeps the part that is correct and valuable: the error-severity validation that flags duplicate language configurations (checkConfiguredLanguageUnique, IssueCodes. DUPLICATE_LANGUAGE_CONFIGURATION, and its test). The correct resolution of a duplicate depends on which inherited value the author intended per block — intent a quick-fix cannot infer and would silently guess wrong — so manual resolution guided by the error is the right behaviour. Removed: the @fix removeDuplicateLanguageConfiguration in CheckCfgQuickfixProvider, the UI-independent CheckCfgQuickfixes core class and its tests, the checkcfg.quickfix package export, the suite entry, and the now-unused UI message keys. Issue dsldevkit#103 asked for "validation and a quick-fix"; we deliver the validation now, and the merge quick-fix is dropped as unsound. Adding language-scoped catalog/parameter uniqueness validation (a pre-existing gap) is left as a separate follow-up. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an error-severity validation that flags duplicate language configurations in a CHECKCFG file.
The grammar accepts multiple
for <Language> { ... }blocks in one configuration, with no defined semantics for how duplicates combine.CheckCfgValidator.checkConfiguredLanguageUniquenow reports an error on eachConfiguredLanguageValidatorthat shares a language name with another, mirroring the existing catalog/check/parameter uniqueness validators and reusing thegetDuplicates()helper. Covered byCheckCfgTest.testDuplicateLanguageNotOk.Validation only, no quick-fix: a quick-fix would have to merge the duplicate blocks, which cannot preserve generated output. Language-level parameters are inherited by inner catalogs/checks and the generator resolves them first-wins per section, so collapsing two blocks into one silently changes which value inner catalogs inherit. The correct resolution depends on author intent, so the error guides the user to resolve duplicates manually.
Closes #103
🤖 Generated with Claude Code